package cn.green.core.excel.impls;

import cn.green.core.excel.model.Column;
import cn.green.core.model.QField;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.green.core.components.field.FieldAuthTypeCom;
import cn.green.core.components.field.FieldCheckTypeCom;
import cn.green.core.components.field.FieldTypeCom;
import cn.green.core.components.store.field.FieldAuthTypeStore;
import cn.green.core.components.store.field.FieldCheckTypeStore;
import cn.green.core.components.store.field.FieldTypeStore;
import cn.green.core.components.store.table.TableTypeStore;
import cn.green.core.components.table.TableTypeCom;
import cn.green.core.excel.QExcel;
import cn.green.core.model.QTable;
import lombok.Getter;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wang.yishu
 * @version 1.0
 * @className QExcelImpl
 * @description QExcel
 * @date 2025/1/7 14:17
 */
@Getter
public class QExcelImpl implements QExcel {

    @Override
    public HSSFCellStyle xlsTitleStyle(HSSFWorkbook workbook) {
        HSSFFont titleFont = workbook.createFont();
        titleFont.setFontName("黑体");
        titleFont.setFontHeightInPoints((short) 11);// 设置字体大小
        HSSFCellStyle titleStyle = workbook.createCellStyle();
         titleStyle.setAlignment((short)2);//横向居中
        titleStyle.setVerticalAlignment((short) 1);//纵向居中
        titleStyle.setFont(titleFont);
        titleStyle.setFillBackgroundColor((short) 13);
        titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
        titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
        titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
        titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
        return titleStyle;
    }

    @Override
    public XSSFCellStyle xlsxTitleStyle(XSSFWorkbook workbook) {
        XSSFFont titleFont = workbook.createFont();
        titleFont.setFontName("黑体");
        titleFont.setFontHeightInPoints((short) 11);// 设置字体大小
        XSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment((short)2);//横向居中
        titleStyle.setVerticalAlignment((short) 1);//纵向居中
        titleStyle.setFont(titleFont);
        titleStyle.setFillBackgroundColor((short) 13);
        titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
        titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
        titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
        titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
        return titleStyle;
    }

    @Override
    public HSSFCellStyle xlsValueStyle(HSSFWorkbook workbook) {
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        HSSFFont valueFont = workbook.createFont();
        cellStyle.setFont(valueFont);
        return cellStyle;
    }

    @Override
    public XSSFCellStyle xlsxValueStyle(XSSFWorkbook workbook) {
        XSSFCellStyle cellStyle = workbook.createCellStyle();
        XSSFFont valueFont = workbook.createFont();
        cellStyle.setFont(valueFont);
        return cellStyle;
    }

    @Override
    public HSSFCellStyle xlsErrTitleStyle(HSSFWorkbook workbook) {
        HSSFFont titleFont = workbook.createFont();
        titleFont.setFontName("黑体");
        titleFont.setFontHeightInPoints((short) 11);// 设置字体大小
        titleFont.setColor(Font.COLOR_RED);
        HSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment((short)2);//横向居中
        titleStyle.setVerticalAlignment((short) 1);//纵向居中
        titleStyle.setFont(titleFont);
        titleStyle.setFillBackgroundColor((short) 13);
        titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
        titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
        titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
        titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
        return titleStyle;
    }

    @Override
    public XSSFCellStyle xlsxErrTitleStyle(XSSFWorkbook workbook) {
        XSSFFont titleFont = workbook.createFont();
        titleFont.setFontName("黑体");
        titleFont.setFontHeightInPoints((short) 11);// 设置字体大小
        titleFont.setColor(Font.COLOR_RED);
        XSSFCellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setAlignment((short)2);//横向居中
        titleStyle.setVerticalAlignment((short) 1);//纵向居中
        titleStyle.setFont(titleFont);
        titleStyle.setFillBackgroundColor((short) 13);
        titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框
        titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框
        titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框
        titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框
        return titleStyle;
    }

    @Override
    public HSSFCellStyle xlsErrorMsgStyle(HSSFWorkbook workbook) {
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        HSSFFont errMsgFont = workbook.createFont();
        errMsgFont.setColor(Font.COLOR_RED);
        cellStyle.setFont(errMsgFont);
        return cellStyle;
    }

    @Override
    public XSSFCellStyle xlsxErrorMsgStyle(XSSFWorkbook workbook) {
        XSSFCellStyle cellStyle = workbook.createCellStyle();
        XSSFFont errMsgFont = workbook.createFont();
        errMsgFont.setColor(Font.COLOR_RED);
        cellStyle.setFont(errMsgFont);
        return cellStyle;
    }


    @Override
    public void templateXls(QTable table, OutputStream outputStream) {
        //todo 这里准备重构
        if (table == null) {
            throw new RuntimeException("QExcel build template error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || tableType.isEmpty()) {
            throw new RuntimeException("QExcel build template error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFCellStyle cellStyle = this.xlsTitleStyle(workbook);
        HSSFSheet sheet = workbook.createSheet(table.getTableName());
        //日期格式禁止自动转换
        HSSFDataFormat dataFormat = workbook.createDataFormat();
        HSSFCellStyle valueStyle = workbook.createCellStyle();
        valueStyle.setDataFormat(dataFormat.getFormat("@"));
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        fields = fields.stream().filter(item -> {
            String fieldAuth = item.getFieldAuth();
            if (fieldAuth == null || fieldAuth.isEmpty()) {
                return false;
            }
            FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
            if (fieldAuthTypeCom != null) {
                return fieldAuthTypeCom.hasInput(item);
            } else {
                return false;
            }
        }).collect(Collectors.toList());
        fields.sort((o1, o2) -> {
            Integer sortO1 = o1.getSort() == null ? 0 : o1.getSort();
            Integer sortO2 = o2.getSort() == null ? 0 : o2.getSort();
            return sortO1.compareTo(sortO2);
        });
        //build title
        HSSFRow titleRow = sheet.createRow(0);
        int index = 0;
        for (QField field : fields) {
            field.setTableName(table.getTableName());
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.hasInput(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                List<HSSFCell> hssfCells = column.generateXlsTitle(workbook, sheet, titleRow);
                                if (hssfCells != null) {
                                    for (HSSFCell hssfCell : hssfCells) {
                                        hssfCell.setCellStyle(cellStyle);
                                        sheet.setDefaultColumnStyle(index, valueStyle);
                                        sheet.autoSizeColumn(index, true);
                                        index++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (tableColumns != null && !tableColumns.isEmpty()) {
                for (Column tableColumn : tableColumns) {
                    tableColumn.setIndex(index);
                    List<HSSFCell> hssfCells = tableColumn.generateXlsTitle(workbook, sheet, titleRow);
                    for (HSSFCell hssfCell : hssfCells) {
                        hssfCell.setCellStyle(cellStyle);
                        index++;
                    }
                }
            }
        }
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void templateXlsx(QTable table, OutputStream outputStream) {
        if (table == null) {
            throw new RuntimeException("QExcel export error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || tableType.isEmpty()) {
            throw new RuntimeException("QExcel export error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFCellStyle cellStyle = this.xlsxTitleStyle(workbook);
        XSSFSheet sheet = workbook.createSheet(table.getTableName());
        //日期格式禁止自动转换
        XSSFDataFormat dataFormat = workbook.createDataFormat();
        XSSFCellStyle valueStyle = workbook.createCellStyle();
        valueStyle.setDataFormat(dataFormat.getFormat("@"));

        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        fields = fields.stream().filter(item -> {
            String fieldAuth = item.getFieldAuth();
            if (fieldAuth == null || fieldAuth.isEmpty()) {
                return false;
            }
            FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
            if (fieldAuthTypeCom != null) {
                return fieldAuthTypeCom.hasInput(item);
            } else {
                return false;
            }
        }).collect(Collectors.toList());
        //build title
        XSSFRow titleRow = sheet.createRow(0);
        int index = 0;

        for (QField field : fields) {
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.hasInput(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                List<XSSFCell> xssfCells = column.generateXlsxTitle(workbook, sheet, titleRow);
                                if (xssfCells != null) {
                                    for (XSSFCell xssfCell : xssfCells) {
                                        xssfCell.setCellStyle(cellStyle);
                                        sheet.setDefaultColumnStyle(index, valueStyle);
                                        sheet.autoSizeColumn(index, true);
                                        index++;
                                    }
                                }

                            }
                        }
                    }
                }
            }
        }
        if (tableColumns != null && !tableColumns.isEmpty()) {
            for (Column tableColumn : tableColumns) {
                tableColumn.setIndex(index);
                List<XSSFCell> xssfCells = tableColumn.generateXlsxTitle(workbook, sheet, titleRow);
                if (xssfCells != null) {
                    for (XSSFCell xssfCell : xssfCells) {
                        xssfCell.setCellStyle(cellStyle);
                        index++;
                    }
                }
            }
        }
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public JSONArray importXls(QTable table, InputStream inputStream) {
        JSONArray importData = new JSONArray();
        if (table == null) {
            throw new RuntimeException("import xls excel file error: table structure is null!");
        }
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("import xls excel file error: field is null!");
        }
        String tableType = table.getTableType();
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        HSSFWorkbook hssfWorkbook;
        try {
            hssfWorkbook = new HSSFWorkbook(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("import xls excel file error: " + e.getMessage());
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //第一页：数据页
        HSSFSheet sheetAt = hssfWorkbook.getSheetAt(0);
        Map<String, Integer> cellIndexMap = new HashMap<>();
        //获取到表头
        HSSFRow titleRow = sheetAt.getRow(0);
        for (int i = 0; ; i++) {
            HSSFCell cell = titleRow.getCell(i);
            if (cell == null) {
                break;
            }
            String cellValue = cell.getStringCellValue();
            if (cellValue == null || cellValue.isEmpty()) {
                break;
            }
            cellIndexMap.put(cellValue, i);
        }
        //获取数据
        for (int i = 1; ;i++) {
            HSSFRow row = sheetAt.getRow(i);
            if (row == null) {
                break;
            }
            JSONObject dataItem = new JSONObject();
            if (tableColumns != null && !tableColumns.isEmpty()) {
                for (Column tableColumn : tableColumns) {
                    Map<String, String> columnNames = tableColumn.columnFieldMaps();
                    if (columnNames == null || columnNames.isEmpty()) {
                        continue;
                    }
                    Map<String, HSSFCell> cellMap = new HashMap<>(columnNames.size());
                    for (String columnName : columnNames.keySet()) {
                        Integer cellIndex = cellIndexMap.get(columnName);
                        if (cellIndex != null) {
                            HSSFCell cell = row.getCell(cellIndex);
                            if (cell != null) {
                                cellMap.put(columnNames.get(columnName), cell);
                            }
                        }
                    }
                    Map<String, Object> valueFromXlsCell = tableColumn.getValueFromXlsCell(cellMap);
                    if (valueFromXlsCell != null) {
                        dataItem.putAll(valueFromXlsCell);
                    }
                }
            }
            for (QField field : fields) {
                field.setTableName(table.getTableName());
                String fieldAuth = field.getFieldAuth();
                if (fieldAuth != null && !fieldAuth.isEmpty()) {
                    FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                    if (fieldAuthTypeCom != null && fieldAuthTypeCom.hasInput(field)) {
                        String fieldType = field.getFieldType();
                        if (fieldType != null && !fieldType.isEmpty()) {
                            FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                            if (fieldTypeCom != null) {
                                List<Column> columns = fieldTypeCom.columns(field);
                                if (columns != null && !columns.isEmpty()) {
                                    for (Column column : columns) {
                                        Map<String, String> columnNames = column.columnFieldMaps();
                                        if (columnNames == null || columnNames.isEmpty()) {
                                            continue;
                                        }
                                        Map<String, HSSFCell> cellMap = new HashMap<>(columnNames.size());
                                        for (String columnName : columnNames.keySet()) {
                                            Integer cellIndex = cellIndexMap.get(columnName);
                                            if (cellIndex != null) {
                                                HSSFCell cell = row.getCell(cellIndex);
                                                if (cell != null) {
                                                    cellMap.put(columnNames.get(columnName), cell);
                                                }
                                            }
                                        }
                                        Map<String, Object> valueFromXlsCell = column.getValueFromXlsCell(cellMap);
                                        if (valueFromXlsCell != null) {
                                            dataItem.putAll(valueFromXlsCell);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            importData.add(dataItem);
        }
        return importData;
    }


    @Override
    public JSONArray importXlsx(QTable table, InputStream inputStream) {
        JSONArray importData = new JSONArray();
        if (table == null) {
            throw new RuntimeException("import xls excel file error: table structure is null!");
        }
        String tableType = table.getTableType();
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("import xls excel file error: field is null!");
        }
        XSSFWorkbook xssfWorkbook;
        try {
            xssfWorkbook = new XSSFWorkbook(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("import xls excel file error: " + e.getMessage());
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        XSSFSheet sheetAt = xssfWorkbook.getSheetAt(0);

        Map<String, Integer> cellIndexMap = new HashMap<>();
        //获取到表头
        XSSFRow titleRow = sheetAt.getRow(0);
        for (int i = 0; ; i++) {
            XSSFCell cell = titleRow.getCell(i);
            if (cell == null) {
                break;
            }
            String cellValue = cell.getStringCellValue();
            if (cellValue == null || "".equals(cellValue)) {
                break;
            }
            cellIndexMap.put(cellValue, i);
        }
        //获取数据
        for (int i = 1; ;i++) {
            XSSFRow row = sheetAt.getRow(i);
            if (row == null) {
                break;
            }
            JSONObject dataItem = new JSONObject();
            if (tableColumns != null && !tableColumns.isEmpty()) {
                for (Column tableColumn : tableColumns) {
                    Map<String, String> columnNames = tableColumn.columnFieldMaps();
                    if (columnNames == null || columnNames.isEmpty()) {
                        continue;
                    }
                    Map<String, XSSFCell> cellMap = new HashMap<>(columnNames.size());
                    for (String columnName : columnNames.keySet()) {
                        Integer cellIndex = cellIndexMap.get(columnName);
                        if (cellIndex != null) {
                            XSSFCell cell = row.getCell(cellIndex);
                            if (cell != null) {
                                cellMap.put(columnNames.get(columnName), cell);
                            }
                        }
                    }
                    Map<String, Object> valueFromXlsCell = tableColumn.getValueFromXlsxCell(cellMap);
                    if (valueFromXlsCell != null) {
                        dataItem.putAll(valueFromXlsCell);
                    }
                }
            }
            for (QField field : fields) {
                field.setTableName(table.getTableName());
                String fieldAuth = field.getFieldAuth();
                if (fieldAuth != null && !fieldAuth.isEmpty()) {
                    FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                    if (fieldAuthTypeCom != null && fieldAuthTypeCom.hasInput(field)) {
                        String fieldType = field.getFieldType();
                        if (fieldType != null && !fieldType.isEmpty()) {
                            FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                            if (fieldTypeCom != null) {
                                List<Column> columns = fieldTypeCom.columns(field);
                                if (columns != null && !columns.isEmpty()) {
                                    for (Column column : columns) {
                                        Map<String, String> columnNames = column.columnFieldMaps();
                                        if (columnNames == null || columnNames.isEmpty()) {
                                            continue;
                                        }
                                        Map<String, XSSFCell> cellMap = new HashMap<>(columnNames.size());
                                        for (String columnName : columnNames.keySet()) {
                                            Integer cellIndex = cellIndexMap.get(columnName);
                                            if (cellIndex != null) {
                                                XSSFCell cell = row.getCell(cellIndex);
                                                if (cell != null) {
                                                    cellMap.put(columnNames.get(columnName), cell);
                                                }
                                            }
                                        }
                                        Map<String, Object> valueFromXlsCell = column.getValueFromXlsxCell(cellMap);
                                        if (valueFromXlsCell != null) {
                                            dataItem.putAll(valueFromXlsCell);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            importData.add(dataItem);
        }
        return importData;
    }


    @Override
    public void exportXls(JSONArray data, QTable table, OutputStream outputStream) {
        if (table == null) {
            throw new RuntimeException("QExcel export error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || "".equals(tableType)) {
            throw new RuntimeException("QExcel export error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFCellStyle titleStyle = this.xlsTitleStyle(workbook);
        HSSFCellStyle valueStyle = this.xlsValueStyle(workbook);
        HSSFSheet sheet = workbook.createSheet(table.getTableName());
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        //build title
        HSSFRow titleRow = sheet.createRow(0);
        List<Column> allColumns = new ArrayList<>();
        int index = 0;

        for (QField field : fields) {
            field.setTableName(table.getTableName());
            List<String> fieldCheck = field.getFieldCheck();
            if (fieldCheck != null) {
                for (String fieldCheckKey : fieldCheck) {
                    FieldCheckTypeCom fieldCheckTypeCom = FieldCheckTypeStore.get(fieldCheckKey);
                    if (fieldCheckTypeCom != null) {
                        if (fieldCheckTypeCom.required()) {
                            field.setAliasName(field.getAliasName() + "*");
                        }
                    }
                }
            }
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.passSelect(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                List<HSSFCell> hssfCells = column.generateXlsTitle(workbook, sheet, titleRow);
                                if (hssfCells != null && !hssfCells.isEmpty()) {
                                    for (HSSFCell hssfCell : hssfCells) {
                                        hssfCell.setCellStyle(titleStyle);
                                        allColumns.add(column);
                                        index++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if (tableColumns != null && !tableColumns.isEmpty()) {
            for (Column tableColumn : tableColumns) {
                tableColumn.setIndex(index);
                List<HSSFCell> hssfCells = tableColumn.generateXlsTitle(workbook, sheet, titleRow);
                if (hssfCells != null && !hssfCells.isEmpty()) {
                    for (HSSFCell hssfCell : hssfCells) {
                        hssfCell.setCellStyle(titleStyle);
                        allColumns.add(tableColumn);
                        index++;
                    }
                }
            }
        }
        if (!allColumns.isEmpty() && data != null && !data.isEmpty()) {
            int rowIndex = 1;
            for (int i = 0; i < data.size(); i++) {
                JSONObject item = data.getJSONObject(i);
                HSSFRow dataRow = sheet.createRow(rowIndex);
                for (Column column : allColumns) {
                    QField field = column.getField();
                    Object cellVal = item.get(field.getFieldName());
                    List<HSSFCell> hssfCells = column.generateXlsCell(workbook, sheet, dataRow, cellVal);
                    if (hssfCells != null && !hssfCells.isEmpty()) {
                        for (HSSFCell hssfCell : hssfCells) {
                            hssfCell.setCellStyle(valueStyle);
                        }
                    }
                }
                rowIndex++;
            }
        }
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void exportXlsx(JSONArray data, QTable table, OutputStream outputStream) {
        if (table == null) {
            throw new RuntimeException("QExcel export error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || "".equals(tableType)) {
            throw new RuntimeException("QExcel export error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFCellStyle titleStyle = this.xlsxTitleStyle(workbook);
        XSSFCellStyle valueStyle = this.xlsxValueStyle(workbook);
        XSSFSheet sheet = workbook.createSheet(table.getTableName());
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        //build title
        XSSFRow titleRow = sheet.createRow(0);
        List<Column> allColumns = new ArrayList<>();
        int index = 0;

        for (QField field : fields) {
            field.setTableName(table.getTableName());
            List<String> fieldCheck = field.getFieldCheck();
            if (fieldCheck != null) {
                for (String fieldCheckKey : fieldCheck) {
                    FieldCheckTypeCom fieldCheckTypeCom = FieldCheckTypeStore.get(fieldCheckKey);
                    if (fieldCheckTypeCom != null) {
                        if (fieldCheckTypeCom.required()) {
                            field.setAliasName(field.getAliasName() + "*");
                        }
                    }
                }
            }
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.passSelect(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                List<XSSFCell> cells = column.generateXlsxTitle(workbook, sheet, titleRow);
                                if (cells != null && !cells.isEmpty()) {
                                    for (XSSFCell xssfCell : cells) {
                                        xssfCell.setCellStyle(titleStyle);
                                        allColumns.add(column);
                                        index++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if (tableColumns != null && !tableColumns.isEmpty()) {
            for (Column tableColumn : tableColumns) {
                tableColumn.setIndex(index);
                List<XSSFCell> xssfCells = tableColumn.generateXlsxTitle(workbook, sheet, titleRow);
                if (xssfCells != null && !xssfCells.isEmpty()) {
                    for (XSSFCell xssfCell : xssfCells) {
                        xssfCell.setCellStyle(titleStyle);
                        allColumns.add(tableColumn);
                        index++;
                    }
                }
            }
        }
        if (!allColumns.isEmpty() && data != null && !data.isEmpty()) {
            int rowIndex = 1;
            for (int i = 0; i < data.size(); i++) {
                JSONObject item = data.getJSONObject(i);
                XSSFRow dataRow = sheet.createRow(rowIndex);
                for (Column column : allColumns) {
                    QField field = column.getField();
                    Object cellVal = item.get(field.getFieldName());
                    List<XSSFCell> xssfCells = column.generateXlsxCell(workbook, sheet, dataRow, cellVal);
                    if (xssfCells != null && !xssfCells.isEmpty()) {
                        for (XSSFCell hssfCell : xssfCells) {
                            hssfCell.setCellStyle(valueStyle);
                        }
                    }
                }
                rowIndex++;
            }
        }
        try {
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public HSSFWorkbook generateErrorXls(JSONArray errorData, QTable table,  String errorMsgColumnName) {
        if (table == null) {
            throw new RuntimeException("QExcel export error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || tableType.isEmpty()) {
            throw new RuntimeException("QExcel export error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFCellStyle cellStyle = this.xlsTitleStyle(workbook);
        HSSFCellStyle errTitleStyle = this.xlsErrTitleStyle(workbook);
        HSSFCellStyle errorMsgStyle = this.xlsErrorMsgStyle(workbook);
        HSSFSheet sheet = workbook.createSheet(table.getTableName());
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        //build title
        HSSFRow titleRow = sheet.createRow(0);
        List<Column> allColumns = new ArrayList<>();
        int index = 0;
        if (tableColumns != null && !tableColumns.isEmpty()) {
            for (Column tableColumn : tableColumns) {
                tableColumn.setIndex(index);
                for (HSSFCell hssfCell : tableColumn.generateXlsTitle(workbook, sheet, titleRow)) {
                    hssfCell.setCellStyle(cellStyle);
                    allColumns.add(tableColumn);
                    index++;
                }
            }
        }
        for (QField field : fields) {
            field.setTableName(table.getTableName());
            List<String> fieldCheck = field.getFieldCheck();
            if (fieldCheck != null) {
                for (String fieldCheckKey : fieldCheck) {
                    FieldCheckTypeCom fieldCheckTypeCom = FieldCheckTypeStore.get(fieldCheckKey);
                    if (fieldCheckTypeCom != null) {
                        if (fieldCheckTypeCom.required()) {
                            field.setAliasName(field.getAliasName() + "*");
                        }
                    }
                }
            }
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.passSelect(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                List<HSSFCell> hssfCells = column.generateXlsTitle(workbook, sheet, titleRow);
                                for (HSSFCell hssfCell : hssfCells) {
                                    hssfCell.setCellStyle(cellStyle);
                                    allColumns.add(column);
                                    index++;
                                }
                            }
                        }
                    }
                }
            }
        }
        HSSFCell errorMsgTitle = titleRow.createCell(allColumns.size());
        errorMsgTitle.setCellType(HSSFCell.CELL_TYPE_STRING);
        errorMsgTitle.setCellValue("错误信息");
        errorMsgTitle.setCellStyle(errTitleStyle);
        if (!allColumns.isEmpty() && errorData != null && !errorData.isEmpty()) {
            int rowIndex = 1;
            for (int i = 0; i < errorData.size(); i++) {
                JSONObject item = errorData.getJSONObject(i);
                HSSFRow dataRow = sheet.createRow(rowIndex);
                for (Column column : allColumns) {
                    QField field = column.getField();
                    Object cellVal = item.get(field.getFieldName());
                    column.generateXlsCell(workbook, sheet, dataRow, cellVal);
                }
                String errorMsg = item.getString(errorMsgColumnName);
                HSSFCell errorMsgCell = dataRow.createCell(allColumns.size());
                errorMsgCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                errorMsgCell.setCellValue(errorMsg);
                errorMsgCell.setCellStyle(errorMsgStyle);
                rowIndex++;
            }
        }
        return workbook;
    }

    @Override
    public XSSFWorkbook generateErrorXlsx(JSONArray errorData, QTable table, String errorMsgColumnName) {
        if (table == null) {
            throw new RuntimeException("QExcel export error: table structure is null!");
        }
        String tableType = table.getTableType();
        if (tableType == null || tableType.isEmpty()) {
            throw new RuntimeException("QExcel export error: table type is null!");
        }
        TableTypeCom tableTypeCom = TableTypeStore.get(tableType);
        List<Column> tableColumns = null;
        if (tableTypeCom != null) {
            tableColumns = tableTypeCom.tableColumns(table);
        }
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFCellStyle cellStyle = this.xlsxTitleStyle(workbook);
        XSSFCellStyle errTitleStyle = this.xlsxErrTitleStyle(workbook);
        XSSFCellStyle errorMsgStyle = this.xlsxErrorMsgStyle(workbook);
        XSSFSheet sheet = workbook.createSheet(table.getTableName());
        List<QField> fields = table.getFields();
        if (fields == null || fields.isEmpty()) {
            throw new RuntimeException("QExcel export error: field is null!");
        }
        //build title
        XSSFRow titleRow = sheet.createRow(0);
        List<Column> allColumns = new ArrayList<>();
        int index = 0;
        if (tableColumns != null && !tableColumns.isEmpty()) {
            for (Column tableColumn : tableColumns) {
                tableColumn.setIndex(index);
                for (XSSFCell xssfCell : tableColumn.generateXlsxTitle(workbook, sheet, titleRow)) {
                    xssfCell.setCellStyle(cellStyle);
                    allColumns.add(tableColumn);
                    index++;
                }

            }
        }
        for (QField field : fields) {
            field.setTableName(table.getTableName());
            List<String> fieldCheck = field.getFieldCheck();
            if (fieldCheck != null) {
                for (String fieldCheckKey : fieldCheck) {
                    FieldCheckTypeCom fieldCheckTypeCom = FieldCheckTypeStore.get(fieldCheckKey);
                    if (fieldCheckTypeCom != null) {
                        if (fieldCheckTypeCom.required()) {
                            field.setAliasName(field.getAliasName() + "*");
                        }
                    }
                }
            }
            String fieldAuth = field.getFieldAuth();
            if (fieldAuth != null && !fieldAuth.isEmpty()) {
                FieldAuthTypeCom fieldAuthTypeCom = FieldAuthTypeStore.get(fieldAuth);
                if (fieldAuthTypeCom.passSelect(field)) {
                    String fieldType = field.getFieldType();
                    if (fieldType != null && !fieldType.isEmpty()) {
                        FieldTypeCom fieldTypeCom = FieldTypeStore.get(fieldType);
                        List<Column> columns = fieldTypeCom.columns(field);
                        if (columns != null) {
                            for (Column column : columns) {
                                column.setIndex(index);
                                for (XSSFCell xssfCell : column.generateXlsxTitle(workbook, sheet, titleRow)) {
                                    xssfCell.setCellStyle(cellStyle);
                                    allColumns.add(column);
                                    index++;
                                }
                            }
                        }
                    }
                }
            }
        }
        XSSFCell errorMsgTitle = titleRow.createCell(allColumns.size());
        errorMsgTitle.setCellType(HSSFCell.CELL_TYPE_STRING);
        errorMsgTitle.setCellValue("错误信息");
        errorMsgTitle.setCellStyle(errTitleStyle);
        if (!allColumns.isEmpty() && errorData != null && !errorData.isEmpty()) {
            int rowIndex = 1;
            for (int i = 0; i < errorData.size(); i++) {
                JSONObject item = errorData.getJSONObject(i);
                XSSFRow dataRow = sheet.createRow(rowIndex);
                for (Column column : allColumns) {
                    QField field = column.getField();
                    Object cellVal = item.get(field.getFieldName());
                    column.generateXlsxCell(workbook, sheet, dataRow, cellVal);
                }
                String errorMsg = item.getString(errorMsgColumnName);
                XSSFCell errorMsgCell = dataRow.createCell(allColumns.size());
                errorMsgCell.setCellType(HSSFCell.CELL_TYPE_STRING);
                errorMsgCell.setCellValue(errorMsg);
                errorMsgCell.setCellStyle(errorMsgStyle);
                rowIndex++;
            }
        }
        return workbook;
    }

}
